﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace d39
{
    public static class Moves
    {
        public static IEnumerable<Vector> Directions = new[] {
            Vector.N, Vector.NE, Vector.E, Vector.SE, Vector.S, Vector.SW, Vector.W, Vector.NW
        }.AsEnumerable();

        private static Dictionary<Vector, char> chars = new Dictionary<Vector, char>
        {
            { Vector.N, 'N'},
            { Vector.NE, 'n'},
            { Vector.E, 'E'},
            { Vector.SE, 'e'},
            { Vector.S, 'S'},
            { Vector.SW, 's'},
            { Vector.W, 'W'},
            { Vector.NW, 'w'},
        };
        private static Dictionary<Vector, string> names = new Dictionary<Vector, string>
        {
            { Vector.N, "N"},
            { Vector.NE, "NE"},
            { Vector.E, "E"},
            { Vector.SE, "SE"},
            { Vector.S, "S"},
            { Vector.SW, "SW"},
            { Vector.W, "W"},
            { Vector.NW, "NW"},
        };

        public static char ToMoveChar(this Vector dir)
        {
            return chars[dir];
        }
        public static Vector FromMoveChar(char ch)
        {
            return (from kv in chars where kv.Value == ch select kv.Key).Single();
        }

        public static string ToMoveString(this IEnumerable<Vector> dirs)
        {
            return string.Join(null, from dir in dirs select ToMoveChar(dir));
        }
        public static IEnumerable<Vector> FromMoveString(string str)
        {
            return from ch in str select FromMoveChar(ch);
        }

        public static IEnumerable<Vector> None { get { return Enumerable.Empty<Vector>(); } }

        public static string ToHumanReadableMoveString(this Vector dir)
        {
            return names.ContainsKey(dir) ? names[dir] : dir.ToHumanReadableString();
        }

        public static Vector ParseHumanReadable(string str)
        {
            return (from kv in names where kv.Value.ToLower() == str.ToLower() select kv.Key).Single();
        }

        public static string ToHumanReadableMoveString(this IEnumerable<Vector> dirs, DnDVersion ver)
        {
            var result = string.Join(", ", from dir in dirs select names[dir]) + " (";
            if (ver == DnDVersion.V35)
            {
                var dist = GetMoveDistance(dirs);
                if (dist == 5)
                {
                    result += "5 foot step";
                }
                else
                {
                    result += dist + "ft";
                }
            }
            else
            {
                result += dirs.Count() + " squares";
            }
            return result + ")";
        }
        public static int GetMoveDistance(this IEnumerable<Vector> dirs)
        {
            return (dirs.Count() + (dirs.Where(dir => names[dir].Length > 1).Count() / 2)) * 5;
        }
    }
}